//Jeffery Zhu
//Rui Liu
//CS380C
//Parser for 3-addr code

#include "parser.h"


void Param::set(ParamType t, int val, string str) {
	type = t;
	value = val;
	literal = str;
}

void Param::parse(string s) {
	int val;
	int i;
	if (s.empty())
		set(NA);
	else if (s.compare("GP") == 0)
		set(GP);
	else if (s.compare("FP") == 0)
		set(FP);
	else if (isNum(s))
		set(CONST, atoi(s.c_str()));
	else if (s[0] == '(' && s[s.size() - 1] == ')')
		set(REG, atoi(s.substr(1, s.size() - 2).c_str()));
	else if (s[0] == '[' && s[s.size() - 1] == ']')
		set(LABEL, atoi(s.substr(1, s.size() - 2).c_str()));
	else if ((i = s.find('#')) != string::npos) {
		string left = s.substr(0, i);
		string right = s.substr(i + 1, s.size() - i - 1);
		int j;
		val = atoi(right.c_str());
		if ((j = left.find_last_of('_')) != string::npos && left.substr(j, left.size() - j).compare("_base") == 0)
			set(ADDR_OFFSET, val, left.substr(0, left.size() - 5));
		else if ((j = left.find_last_of('_')) != string::npos
			&& left.substr(j, left.size() - j).compare("_offset") == 0)
			set(FIELD_OFFSET, val, left.substr(0, left.size() - 7));
		else
			set(LOCAL_VAR, val, left);
	} else
		set(NA);
}


bool Param::isNum(string s) {
	if (s.empty() || (s.at(0) != '-' && !isdigit(s.at(0))))
		return false;

	for (int i = 1; i < s.size(); i++) {
		if (!isdigit(s.at(i)))
			return false;
	}
	return true;
}


void Instr::parse(string s) {
	stringstream ss(s);
	string o, p1, p2;
	ss >> o;
	ss >> o;
	ss >> o;
	ss >> p1;
	ss >> p2;
	this->opt = parseOpt(o);
	this->param1.parse(p1);
	this->param2.parse(p2);
}

Operator Instr::parseOpt(string o) {
	if (o.compare("nop") == 0)
		return NOP;
	else if (o.compare("add") == 0)
		return ADD;
	else if (o.compare("sub") == 0)
		return SUB;
	else if (o.compare("mul") == 0)
		return MUL;
	else if (o.compare("div") == 0)
		return DIV;
	else if (o.compare("mod") == 0)
		return MOD;
	else if (o.compare("neg") == 0)
		return NEG;
	else if (o.compare("cmpeq") == 0)
		return CMPEQ;
	else if (o.compare("cmple") == 0)
		return CMPLE;
	else if (o.compare("cmplt") == 0)
		return CMPLT;
	else if (o.compare("br") == 0)
		return BR;
	else if (o.compare("blbc") == 0)
		return BLBC;
	else if (o.compare("blbs") == 0)
		return BLBS;
	else if (o.compare("call") == 0)
		return CALL;
	else if (o.compare("load") == 0)
		return LOAD;
	else if (o.compare("store") == 0)
		return STORE;
	else if (o.compare("move") == 0)
		return MOVE;
	else if (o.compare("read") == 0)
		return READ;
	else if (o.compare("write") == 0)
		return WRITE;
	else if (o.compare("wrl") == 0)
		return WRL;
	else if (o.compare("param") == 0)
		return PARAM;
	else if (o.compare("enter") == 0)
		return ENTER;
	else if (o.compare("ret") == 0)
		return RET;
	else if (o.compare("entrypc") == 0)
		return ENTRYPC;
	else
		return UNDEF;
}
